{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Rational10:\n",
    "    def __init__(self, num, den=1):\n",
    "        self.num = num\n",
    "        self.den = den \n",
    "        \n",
    "    def plus(self, another):\n",
    "        den = self.den * another.den\n",
    "        num = (self.num * another.den + self.den * another.num)\n",
    "        return Rational10(num, den)\n",
    "    \n",
    "    def print(self):\n",
    "        print(str(self.num)+'/'+str(self.den))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "80/75\n"
     ]
    }
   ],
   "source": [
    "r1 = Rational10(3,5)\n",
    "r2 = r1.plus(Rational10(7,15))\n",
    "\n",
    "r2.print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 由下划线 _ 开头的函数名都当作内部使用的而名字，不应该在这个类之外使用\n",
    "\n",
    "# python 对类定义里以两个下划线开头（但不以两个下划线结尾）的名字做了特殊处理，使得在类定义之外不能直接访问"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 静态方法\n",
    "# 静态方法参数列表中不应该有self 参数，在其他方面没有任何限制。\n",
    "# 本质上，静态方法就是在类定义里面定义的普通函数，也是该类的局部函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2\n",
      "(1, '/', 2)\n",
      "1 / 2\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "class Rational:\n",
    "    @staticmethod\n",
    "    def _gcd(m, n):\n",
    "        if n==0:\n",
    "            m, n = n, m\n",
    "        while m != 0:\n",
    "            m, n = n%m, m\n",
    "        return n\n",
    "    \n",
    "    def __init__(self, num, den=1):\n",
    "        if not isinstance(num, int) or not isinstance(den, int):\n",
    "            raise TypeError\n",
    "        if den == 0:\n",
    "            raise ZeroDivisionError\n",
    "        sign = 1\n",
    "        if num < 0:\n",
    "            num, sign = -num, -sign\n",
    "        if den < 0:\n",
    "            den, sign = -den, -sign \n",
    "        g = Rational._gcd(num, den)\n",
    "        self._num = sign*(num//g)\n",
    "        self._den = den//g\n",
    "    \n",
    "    def num(self):\n",
    "        return self._num\n",
    "    \n",
    "    def den(self):\n",
    "        return self._den \n",
    "    \n",
    "    def __add__(self, another):\n",
    "        den = self._den * another.den()\n",
    "        num = (self._num * another.den() + self._den*another.num())\n",
    "        return Rational(num, den)\n",
    "    \n",
    "    def __mul__(self, another):\n",
    "        return Rational(self._num * another.num(),\n",
    "                       self._den * another.den())\n",
    "    \n",
    "    def __floordiv(self, another):\n",
    "        if another.num() == 0:\n",
    "            raise ZeroDivisionError\n",
    "        return Rational(self._num * another.den, self._den*another.num)\n",
    "    \n",
    "    def __str__(self):\n",
    "        return (self._num, '/', self._den)\n",
    "    \n",
    "    def print(self):\n",
    "        print(self._num, '/', self._den)\n",
    "        \n",
    "r = Rational(5, 10)\n",
    "print(r._num, r._den)\n",
    "r.__add__(Rational(1,2)).den()\n",
    "\n",
    "print(r.__str__())\n",
    "print(r.print())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5 3\n",
      "3 2\n",
      "2 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def gcd(a, b):\n",
    "    if b>a:\n",
    "        a, b = b, a \n",
    "    while b!=0:\n",
    "        print(a, b)\n",
    "        a, b = b, a%b\n",
    "    return a\n",
    "\n",
    "gcd(5,3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 静态方法和类方法\n",
    "* 静态方法\n",
    "    * 在def前加@staticmethod,静态方法实际上是普通函数，只是出于需要定义在类里\n",
    "\n",
    "* 类方法\n",
    "    * 在def前加@classmethod。类方法必须有一个表示其调用类的参数，习惯将cls作为参数，还可以任意多个其他参数。\n",
    "    * 类方法也是类对象的属性，可以属性访问形式条用。在类方法执行时，调用它的类将自动约束到方法的cls 参数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "class Counterable:\n",
    "    counter = 0 \n",
    "    \n",
    "    def __init__(self):\n",
    "        Counterable.counter += 1\n",
    "        \n",
    "    @classmethod\n",
    "    def get_count(cls):\n",
    "        return Counterable.counter\n",
    "    \n",
    "\n",
    "x = Counterable()\n",
    "y = Counterable()\n",
    "z = Counterable()\n",
    "print(Counterable.get_count())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 约定以单下划线开头的为私有变量，不要从外部访问"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
